// 题目描述
// 2725. 间隔取消
// 难度
// 简单
// 1
// 现给定一个函数 fn，一个参数数组 args 和一个时间间隔 t，返回一个取消函数 cancelFn。函数 fn 应该立即使用 args 调用，并且在每个 t 毫秒内再次调用，直到调用 cancelFn。
//   示例 1：
// 输入：fn = (x) => x * 2, args = [4], t = 20, cancelT = 110
// 输出：
// [
//    {"time": 0, "returned": 8},
//    {"time": 20, "returned": 8},
//    {"time": 40, "returned": 8},
//    {"time": 60, "returned": 8},
//    {"time": 80, "returned": 8},
//    {"time": 100, "returned": 8}
// ]
// 解释：
// const cancelT = 110
// const cancel = cancellable(x => x * 2, [4], 20);
// setTimeout(cancel, cancelT);
// 每隔 20ms，调用 fn(4)。
// 第一次调用 fn 是在 0ms。fn(4) 返回 8。
// 第二次调用 fn 是在 20ms。fn(4) 返回 8。
// 第三次调用 fn 是在 40ms。fn(4) 返回 8。
// 第四次调用 fn 是在 60ms。fn(4) 返回 8。
// 第五次调用 fn 是在 80ms。fn(4) 返回 8。
// 第六次调用 fn 是在 100ms。fn(4) 返回 8。
// 在 t=110ms 时取消。
// 示例 2：
// 输入：fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 25, cancelT = 140
// 输出：
// [
//    {"time": 0, "returned": 10},
//    {"time": 25, "returned": 10},
//    {"time": 50, "returned": 10},
//    {"time": 75, "returned": 10},
//    {"time": 100, "returned": 10},
//    {"time": 125, "returned": 10}
// ]
// 解释：
// const cancelT = 140
// const cancel = cancellable((x1, x2) => (x1 * x2), [2, 5], 25);
// setTimeout(cancel, cancelT);
//
// 每隔 25ms，调用 fn(2, 5)。直到 t=140ms，然后取消。
// 第一次调用 fn 是在 0ms
// 第二次调用 fn 是在 25ms
// 第三次调用 fn 是在 50ms
// 第四次调用 fn 是在 75ms
// 第五次调用 fn 是在 100ms
// 第六次调用 fn 是在 125ms
// 在 140ms 取消
// 示例 3：
// 输入：fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50, cancelT = 180
// 输出：
// [
//    {"time": 0, "returned": 9},
//    {"time": 50, "returned": 9},
//    {"time": 100, "returned": 9},
//    {"time": 150, "returned": 9}
// ]
// 解释：
// const cancelT = 180
// const cancel = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50);
// setTimeout(cancel, cancelT);
//
// 每隔 50ms，调用 fn(5, 1, 3)。直到 t=180ms，然后取消。
// 第一次调用 fn 是在 0ms
// 第二次调用 fn 是在 50ms
// 第三次调用 fn 是在 100ms
// 第四次调用 fn 是在 150ms
// 在 180ms 取消
//   提示：
// fn 是一个函数
// args 是一个有效的 JSON 数组
// 1 <= args.length <= 10
// 20 <= t <= 1000
// 10 <= cancelT <= 1000
// 通过次数1,207提交次数1,662
// https://leetcode.cn/problems/interval-cancellation/

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function (fn, args, t) {
  fn(...args)
  const timer = setInterval(() => {
    fn(...args)
  }, t)

  return function () {
    timer && clearInterval(timer)
  }
}

/**
 *  const result = []
 *
 *  const fn = (x) => x * 2
 *  const args = [4], t = 20, cancelT = 110
 *
 *  const start = performance.now()
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start)
 *      result.push({"time": diff, "returned": fn(...argsArr)})
 *  }
 *
 *  const cancel = cancellable(log, args, t);
 *
 *  setTimeout(() => {
 *     cancel()
 *  }, cancelT)
 *
 *  setTimeout(() => {
 *    console.log(result)  // [
 *                         //      {"time":0,"returned":8},
 *                         //      {"time":20,"returned":8},
 *                         //      {"time":40,"returned":8},
 *                         //      {"time":60,"returned":8},
 *                         //      {"time":80,"returned":8},
 *                         //      {"time":100,"returned":8}
 *                         //  ]
 *  }, cancelT + t + 15)
 */
